package com.epalmpay.service.trade.impl;

import com.epalmpay.bean.MerchantSettedRecordBean;
import com.epalmpay.bean.TradeOfflineBean;
import com.epalmpay.exception.ApplicationException;
import com.epalmpay.status.Rescode;
import com.epalmpay.dto.order.OrderTradeInDTO;
import com.epalmpay.dto.order.OrderTradeListOutDTO;
import com.epalmpay.dto.order.OrderTradeOutDTO;
import com.epalmpay.dto.trade.*;
import com.epalmpay.entity.Group;
import com.epalmpay.entity.MemberCard;
import com.epalmpay.entity.MerchantSettedRecord;
import com.epalmpay.entity.Page;
import com.epalmpay.entity.Shop;
import com.epalmpay.entity.ShopGroupRelation;
import com.epalmpay.entity.TradeOffline;
import com.epalmpay.enumdef.BizEnum;
import com.epalmpay.enumdef.CommonEnum;
import com.epalmpay.enumdef.BizEnum.MerchantSettedStatus;
import com.epalmpay.mapper.CouponUserMapper;
import com.epalmpay.mapper.GroupMapper;
import com.epalmpay.mapper.MemberCardMapper;
import com.epalmpay.mapper.MerchantSettedRecordMapper;
import com.epalmpay.mapper.OrderGoodItemMapper;
import com.epalmpay.mapper.OrderServiceGoodDetailMapper;
import com.epalmpay.mapper.ShopGroupRelationMapper;
import com.epalmpay.mapper.ShopMapper;
import com.epalmpay.mapper.TradeOfflineMapper;
import com.epalmpay.payplat.IPayAPI;
import com.epalmpay.payplat.PayBalanceChange;
import com.epalmpay.payplat.result.PayResult;
import com.epalmpay.service.trade.ITradeService;
import com.epalmpay.util.DateUtil;
import com.epalmpay.util.Logger;
import com.epalmpay.util.PropertyCopyUtil;
import com.epalmpay.util.Response;
import com.epalmpay.util.StringUtil;
import com.epalmpay.util.SysUtils;
import com.epalmpay.util.Tools;
import com.epalmpay.util.payplat.DateUtils;
import com.epalmpay.util.payplat.UtilFun;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * Created by wucongpeng on 2017/5/4.
 */

@Service("tradeService")
public class TradeServiceImpl implements ITradeService {

	protected Logger logger = Logger.getLogger(this.getClass());

    @Resource
    private TradeOfflineMapper tradeOfflineMapper;
    @Resource
    private MemberCardMapper memberCardMapper;
    
    @Resource
    private MerchantSettedRecordMapper merchantSettedRecordMapper;

    @Resource
    private OrderServiceGoodDetailMapper orderServiceGoodDetailMapper;
    
    @Resource
    private OrderGoodItemMapper  orderGoodItemMapper;

    @Resource
	private GroupMapper groupMapper;
	@Resource
	private ShopMapper shopMapper;
	
	@Resource
	private ShopGroupRelationMapper shopGroupRelationMapper;
	@Resource
	private CouponUserMapper couponUserMapper;
    /**交易记录列表分页
     * @return
     * @throws Exception
     */
    @Override
    public TradeWalletListOutDTO getTradeWalletList(TradeWalletInDTO tradeWalletInDTO, Page page)throws Exception{

        TradeWalletListOutDTO result = new TradeWalletListOutDTO();

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("groupId", tradeWalletInDTO.getGroupId());
        map.put("shopId", tradeWalletInDTO.getShopId());
        map.put("agent", tradeWalletInDTO.getAgentId());
        map.put("transactionType", tradeWalletInDTO.getTransactionType());
        map.put("payType", tradeWalletInDTO.getPayType());
        map.put("transactionStatus", tradeWalletInDTO.getTransactionStatus());
        map.put("startDate", tradeWalletInDTO.getStartDate());
        map.put("endDate", tradeWalletInDTO.getEndDate());
        map.put("orderId", tradeWalletInDTO.getOrderId());

        int sumCount = tradeOfflineMapper.selectTradeWalletListCount(map);

        page.setTotalResult(sumCount);
        if(sumCount<=0) {
            return result;
        }
        map.put("limit", page.getShowCount());
        map.put("start", page.getShowCount()*(page.getCurrentPage()-1));

        List<TradeWalletOutDTO> tradeWalletOutDTOList = tradeOfflineMapper.selectTradeWalletList(map);
        result.setTradeWalletOutDTOList(tradeWalletOutDTOList);
        return result;
    }


    /**交易记录列表分页
     * @return
     * @throws Exception
     */
    @Override
    public TradeListOutDTO listOnlineRecords(TradeInDTO tradeInDTO, Page page)throws Exception{

        TradeListOutDTO result = new TradeListOutDTO();

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("groupId", tradeInDTO.getGroupId());
        map.put("shopId", tradeInDTO.getShopId());
        map.put("agentId", tradeInDTO.getAgentId());
        map.put("transactionStatus", tradeInDTO.getTransactionStatus());
        map.put("goodType", tradeInDTO.getGoodType());
        map.put("payType", tradeInDTO.getPayType());
        map.put("cardNo", tradeInDTO.getCardNo());
        map.put("orderId", tradeInDTO.getOrderId());
        map.put("joinStart", tradeInDTO.getJoinStart());
        map.put("joinEnd", tradeInDTO.getJoinEnd());

        int sumCount = tradeOfflineMapper.selectOnlineTradeListCount(map);

        page.setTotalResult(sumCount);
        if(sumCount<=0) {
            return result;
        }
        map.put("limit", page.getShowCount());
        map.put("start", page.getShowCount()*(page.getCurrentPage()-1));

        List<TradeOffline> tradeOfflines = tradeOfflineMapper.selectOnlineTradeList(map);
        result.setTradeOfflineList(tradeOfflines);

        return result;
    }


    /**交易记录列表分页
     * @return
     * @throws Exception
     */
    @Override
    public OrderTradeListOutDTO listOnlineOrderRecords(OrderTradeInDTO orderTradeInDTO, Page page)throws Exception{

        OrderTradeListOutDTO result = new OrderTradeListOutDTO();

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("groupId", orderTradeInDTO.getGroupId());
        map.put("shopId", orderTradeInDTO.getShopId());
        map.put("mallOrderStatus", orderTradeInDTO.getOrderStatus());
        map.put("orderNo", orderTradeInDTO.getOrderNo());
        map.put("joinStart", orderTradeInDTO.getJoinStart());
        map.put("joinEnd", orderTradeInDTO.getJoinEnd());

        int sumCount = orderServiceGoodDetailMapper.selectOrderTradeListCount(map);

        page.setTotalResult(sumCount);
        if(sumCount<=0) {
            return result;
        }
        map.put("limit", page.getShowCount());
        map.put("start", page.getShowCount()*(page.getCurrentPage()-1));

        List<Map<String,Object>> orderDetailOutDTOList = orderServiceGoodDetailMapper.selectOrderTradeList(map);
        List<OrderTradeOutDTO> list = new ArrayList<OrderTradeOutDTO>();

        for(Map<String, Object> orderDetail : orderDetailOutDTOList){
            OrderTradeOutDTO out = new OrderTradeOutDTO();
            out.setId((Long) orderDetail.get("id"));
            out.setCouponStatus((Integer) orderDetail.get("coupon_status"));
            out.setOrderStatus((Integer) orderDetail.get("orderStatus"));
            out.setMemberName((String) orderDetail.get("memberName"));
            out.setOrderNo((orderDetail.get("order_no"))+"");
            out.setOriginalPrice((Integer) orderDetail.get("original_price"));
            out.setPrice((Integer) orderDetail.get("price"));
            out.setSettingPrice((Integer) orderDetail.get("setting_price"));
            out.setVerifyTime((Date) orderDetail.get("verify_time"));
            list.add(out);
        }


        result.setOrderTradeOutDTOList(list);


        return result;
    }

    @Override
    public Response ysTradeList(Long memberId, Integer page, Byte transactionType) {
        Integer start = (page - 1) * 10;
        return null;
    }

    @Override
    public Map<String, Object> getMemberTradeList(String memberId, String datefrom, String dateto, String type,
                                                  String memo, Integer pageNo, Integer pageSize) throws Exception{
        Map<String, Object> map = new HashMap<String, Object>();
        if (Tools.isEmpty(memberId)) {
            throw new ApplicationException(Rescode.FAIL,"memberId 不能为空！");
        }
        if (Tools.isEmpty(datefrom)) {
            throw new ApplicationException(Rescode.FAIL,"datefrom 不能为空！");
        }
        if (Tools.isEmpty(dateto)) {
            throw new ApplicationException(Rescode.FAIL,"dateto 不能为空！");
        }
        if (pageNo == null) {
            throw new ApplicationException(Rescode.FAIL,"pageNo 不能为空！");
        }
        if (pageSize == null) {
            throw new ApplicationException(Rescode.FAIL,"pageSize 不能为空！");
        }

        HashMap<String,Object> param=new HashMap<String,Object>();

        param.put("memberId", Long.parseLong(memberId));
        param.put("datefrom", datefrom);
        param.put("dateto", dateto);
        param.put("type", type);
        param.put("memo", memo);
        param.put("start", (pageNo -1)*pageSize);
        param.put("limit", pageSize);

        List<TradeOfflineBean> tradeOfflines = tradeOfflineMapper.queryMemberTradeList(param);
        if (tradeOfflines == null || tradeOfflines.size()==0){
            return map;
        }

        List<Map<String,Object>> tradeList = new ArrayList<Map<String, Object>>();

        for(TradeOfflineBean tradeOffline:tradeOfflines){
            Map<String, Object> tradeMap = new HashMap<String, Object>();

            if(StringUtils.isNotEmpty(tradeOffline.getPayAccount())){
                MemberCard mem = memberCardMapper.querycardName(tradeOffline.getPayAccount());
                if(mem!=null) {
                    tradeMap.put("cardName", mem.getIssuerBankName());
                }
            }else{
                tradeMap.put("cardName",null);
            }

            if(tradeOffline.getTransactionType()== BizEnum.TransactionType.Profit.getType()
                    || tradeOffline.getTransactionType()==BizEnum.TransactionType.RedPackage.getType()){
                tradeMap.put("payerName",tradeOffline.getReceiverName());
                tradeMap.put("payerPic",tradeOffline.getReceiverPic());
            }
            if(tradeOffline.getPayerId() !=null){
                if(tradeOffline.getPayerId().equals(memberId)){
                    tradeMap.put("payerName",tradeOffline.getReceiverName());
                    tradeMap.put("payerPic",tradeOffline.getReceiverPic());
                }else{
                    tradeMap.put("payerPic",tradeOffline.getPayerPic());
                    tradeMap.put("payerName",tradeOffline.getPayerName());
                }
            }

            tradeMap.put("userId",tradeOffline.getPayerId());
            tradeMap.put("order_id",tradeOffline.getOrderId());
            tradeMap.put("type",tradeOffline.getTransactionType());
            tradeMap.put("time",DateUtil.fomatDate(tradeOffline.getGmtCreate(),DateUtil.sdfTime));
            tradeMap.put("amount",tradeOffline.getRealAmount());
            tradeMap.put("status",tradeOffline.getTransactionStatus());
            tradeList.add(tradeMap);
        }
        if(tradeList.size()>0) {
            map.put("trade_list", tradeList);
        }

        return map;

    }


	@Override
	public MerchantSettedListOutDTO settedRecordList(MerchantSettedInDTO merchantSettedInDTO, Page page) throws Exception {
		MerchantSettedListOutDTO result = new MerchantSettedListOutDTO();

	        Map<String, Object> map = new HashMap<String, Object>();
	        map.put("groupId", merchantSettedInDTO.getGroupId());
	       
	        map.put("settedType", merchantSettedInDTO.getSettedType());
	        map.put("settedStatus", merchantSettedInDTO.getSettedStatus());
	        map.put("joinStart", merchantSettedInDTO.getJoinStart());
	        map.put("joinEnd", merchantSettedInDTO.getJoinEnd());
	        map.put("shopName", merchantSettedInDTO.getShopName());
	        map.put("shopId", merchantSettedInDTO.getShopId());
	        int sumCount = merchantSettedRecordMapper.selectMerchantSettedRecordCount(map);

	        page.setTotalResult(sumCount);
	        if(sumCount<=0) {
	            return result;
	        }
	        map.put("limit", page.getShowCount());
	        map.put("start", page.getShowCount()*(page.getCurrentPage()-1));

	        List<MerchantSettedRecordBean> merchantSettedRecordList = merchantSettedRecordMapper.selectMerchantSettedRecord(map);
	        result.setMerchantSettedRecords(merchantSettedRecordList);
	        return result;
	}


	@Override
	public boolean finishMerChantSetted(SettedBaseInDTO settedBaseInDTO) throws Exception {
		
		 MerchantSettedRecord merchantSettedRecord=merchantSettedRecordMapper.selectByPrimaryKey(settedBaseInDTO.getRecordId());
		 Shop shop = shopMapper.selectByPrimaryKey(merchantSettedRecord.getShopId());
	        Group group = groupMapper.selectByPrimaryKey(merchantSettedRecord.getGroupId());
	        ShopGroupRelation shopGroupRelation = shopGroupRelationMapper.selectShopInfo(group.getId(),shop.getId());
	        if(shopGroupRelation == null){
	        	throw new ApplicationException("结算商户不属于大商户");
	        }
	            
	        String amountDes=SysUtils.string2MD5(merchantSettedRecord.getAmount() + SysUtils.formatString(merchantSettedRecord.getShopId(), 7));
	       if(!amountDes.equals(merchantSettedRecord.getAmountDes())){
	    	   throw new ApplicationException("结算金额不能手动修改");
	       }
		PayBalanceChange payBalanceChange = PayBalanceChange.initialize(group.getPayGroupCode(),
                shopGroupRelation.getPayMerchantCode(),merchantSettedRecord.getAmount().toString(), "1",
                merchantSettedRecord.getOutOrderNum(), DateUtils.getDateTimeString("yyyyMMddHHmmss"), StringUtil.getRandNumberStr(10), "156");
        PayResult payResult = IPayAPI.consumptionBalanceChangeMerchant(payBalanceChange);
        if(payResult==null||!payResult.getRespCode().equals("0000")) {
            logger.error("商家:" + shop.getMerchantName() + "(" + merchantSettedRecord.getShopId() + ")"  + "打款失败!");
            String newOrgOrderNum = UtilFun.createOrderNum();
            merchantSettedRecord.setOutOrderNum(newOrgOrderNum);
            merchantSettedRecord.setStatus(MerchantSettedStatus.merchantSettedFail.getType());
       	   merchantSettedRecordMapper.updateByPrimaryKey(merchantSettedRecord);
            return false;
        }

        try {
            //交易记录创建
            TradeOffline tradeOffline = new TradeOffline();
            tradeOffline.setGmtCreate(new Date());
            tradeOffline.setGmtModified(new Date());
            tradeOffline.setGroupId(group.getId());
            tradeOffline.setOrderId(merchantSettedRecord.getOutOrderNum());
            tradeOffline.setPayerId(group.getId());
            tradeOffline.setPayerName(group.getMerchantName());
            tradeOffline.setPayerType((byte) CommonEnum.UserType.BusinessManager.getType());
            tradeOffline.setReceiverId(shop.getId().toString());
            tradeOffline.setReceiverName(shop.getMerchantName());
            tradeOffline.setReceiverType((byte) CommonEnum.UserType.Store.getType());
            tradeOffline.setTransactionType((byte)  BizEnum.TransactionType.AddBalanceMerchant.getType());
            tradeOffline.setSubType((byte) BizEnum.PaymentScene.Online.getType());
            tradeOffline.setOrderAmount(merchantSettedRecord.getAmount());
            tradeOffline.setIsWallet(true);
            tradeOffline.setRealAmount(merchantSettedRecord.getAmount());
            tradeOffline.setPayType((byte) BizEnum.PaymentType.Wallet.getType());
            tradeOffline.setTransactionStatus((byte) BizEnum.TransactionStatus.Success.getType());
            tradeOffline.setTransOrderNo(payResult.getOrderId());
            if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.couperSetted.getType())){
            	 tradeOffline.setMemo("券码核销结算");
            }else if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.goodsSetted.getType())){
            	
            	 tradeOffline.setMemo("商城商品结算");
            }else if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.serviceGoodsSetted.getType())){
            	
            	 tradeOffline.setMemo("服务商品结算");
            }
           
            int  result = tradeOfflineMapper.insertSelective(tradeOffline);

          
          //更新订单明细状态
            merchantSettedRecord.setLastOrderNum(payBalanceChange.getOrgOrderNum());
            merchantSettedRecord.setSuccessOrderId(tradeOffline.getId());
            merchantSettedRecord.setStatus(BizEnum.MerchantSettedStatus.merchantSetted.getType());
            merchantSettedRecordMapper.updateByPrimaryKey(merchantSettedRecord);
            if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.couperSetted.getType())){
            	result =couponUserMapper.updateShopSettingInfoByMerchantSetId(tradeOffline.getId(),merchantSettedRecord.getId());
            }else if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.goodsSetted.getType())){
            	
            	 result = orderGoodItemMapper.updateShopSettingInfoByMerchantSetId(tradeOffline.getId(),merchantSettedRecord.getId());
            }else if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.serviceGoodsSetted.getType())){
            	
           	 result = orderServiceGoodDetailMapper.updateShopSettingInfoByMerchantSetId(tradeOffline.getId(),merchantSettedRecord.getId());
           }
           
          return true;
        }catch (Exception e) {
           
            e.printStackTrace();
            throw e;
        }
	}


	@Override
	public MerchantSettedInfoOutDTO getMerchantSettedInfo(SettedBaseInDTO merchantSettedInfoInDTO, Page page) throws Exception {
		MerchantSettedInfoOutDTO merchantSettedInfoOutDTO=new MerchantSettedInfoOutDTO();
		MerchantSettedRecord merchantSettedRecord= merchantSettedRecordMapper.selectByPrimaryKey(merchantSettedInfoInDTO.getRecordId());
		PropertyCopyUtil.copyPPropertiesNotNull(merchantSettedRecord, merchantSettedInfoOutDTO);
	
		 Map<String, Object> map = new HashMap<String, Object>();
	        map.put("groupId", merchantSettedInfoInDTO.getGroupId());
	       
	        map.put("merchantSettedRecordId", merchantSettedInfoInDTO.getRecordId());
	       
	       
	        if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.couperSetted.getType())){
	        	 int sumCount = couponUserMapper.selectInfoByMerchantSettedCount(map);

	 	        page.setTotalResult(sumCount);
	 	        if(sumCount<=0) {
	 	        	merchantSettedInfoOutDTO.setMerchantSettedInfos(new ArrayList());
	 	        }
	 	        map.put("limit", page.getShowCount());
	 	        map.put("start", page.getShowCount()*(page.getCurrentPage()-1));

	 	       List couponUserList = couponUserMapper.selectInfoByMerchantSetted(map);
	 	       merchantSettedInfoOutDTO.setMerchantSettedInfos(couponUserList);
            }else if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.goodsSetted.getType())){
            	int sumCount = orderGoodItemMapper.selectInfoByMerchantSettedCount(map);

	 	        page.setTotalResult(sumCount);
	 	        if(sumCount<=0) {
	 	        	merchantSettedInfoOutDTO.setMerchantSettedInfos(new ArrayList());
	 	        }
	 	        map.put("limit", page.getShowCount());
	 	        map.put("start", page.getShowCount()*(page.getCurrentPage()-1));

	 	       List  orderGoodItemList = orderGoodItemMapper.selectInfoByMerchantSetted(map);
	 	       merchantSettedInfoOutDTO.setMerchantSettedInfos(orderGoodItemList);
            	
            }else if(merchantSettedRecord.getType().equals(BizEnum.MerchantSettedType.serviceGoodsSetted.getType())){
            	
            	int sumCount = orderServiceGoodDetailMapper.selectInfoByMerchantSettedCount(map);

	 	        page.setTotalResult(sumCount);
	 	        if(sumCount<=0) {
	 	        	merchantSettedInfoOutDTO.setMerchantSettedInfos(new ArrayList());
	 	        }
	 	        map.put("limit", page.getShowCount());
	 	        map.put("start", page.getShowCount()*(page.getCurrentPage()-1));

	 	       List serviceGoodDetailList = orderServiceGoodDetailMapper.selectInfoByMerchantSetted(map);
	 	       merchantSettedInfoOutDTO.setMerchantSettedInfos(serviceGoodDetailList);
           }
	       

		return merchantSettedInfoOutDTO;
	}


	@Override
	public MerchantSettedDetailOutDTO merchantSettedDetai(SettedBaseInDTO settedBaseInDTO) throws Exception {

		return merchantSettedRecordMapper.selectInfoById(settedBaseInDTO.getRecordId());
	}

    @Override
    public TradeOffline selectByOrderId(String orderId) throws Exception {
        return tradeOfflineMapper.selectByOrderId(orderId);
    }
}
